//
// Created by fanghr on 18-3-30.
//
#include "../include/thread_gestrec.h"
#include "../include/thread_mat.h"
#include "../../camsrv/gestrecn/include/gestrec.h"

static void *gestrec(void *);

static void *gestrec_sub(void *);

thread_gestrec::thread_gestrec(thread_mat &r_mat, thread_mat &l_mat) : l(l_mat), r(r_mat) {
    is_run = is_gestrec_already = false;
    pthread_rwlock_init(&rwlock, nullptr);

}

thread_gestrec::~thread_gestrec() {
    stop();
    pthread_rwlock_destroy(&rwlock);
}

int thread_gestrec::run() {
    if (is_run)
        return 0;
    if (pthread_create(&thread, nullptr, gestrec, this))
        return -1;
    is_run = true;
    return 0;
}

int thread_gestrec::stop() {
    if (!is_run)
        return 0;
    if (pthread_cancel(thread))
        return -1;
    is_run = false;
    return 0;
}

static void *gestrec(void *obj) {
    auto ptr = (thread_gestrec *) obj;
    do {
        pthread_rwlock_rdlock(&ptr->r.after_preproc.rwlock_preproc);
        if (ptr->r.after_preproc.is_after_pre_comp_data_ready = true) {
            pthread_rwlock_unlock(&ptr->r.after_preproc.rwlock_preproc);
            break;
        }
        pthread_rwlock_unlock(&ptr->r.after_preproc.rwlock_preproc);

    } while (true);
    do {
        pthread_rwlock_rdlock(&ptr->l.after_preproc.rwlock_preproc);
        if (ptr->l.after_preproc.is_after_pre_comp_data_ready = true) {
            pthread_rwlock_unlock(&ptr->l.after_preproc.rwlock_preproc);
            break;
        }
        pthread_rwlock_unlock(&ptr->l.after_preproc.rwlock_preproc);

    } while (true);

    pthread_t sub_r, sub_l;
    int *return_l, *return_r;
    int tmp;
    while (true) {
        pthread_create(&sub_l, nullptr, gestrec_sub, &ptr->r);
        pthread_create(&sub_r, nullptr, gestrec_sub, &ptr->l);
        pthread_join(sub_l, (void **) &return_l);
        pthread_join(sub_r, (void **) &return_r);
        tmp = (*return_l + *return_r) / 2;
        pthread_rwlock_wrlock(&ptr->rwlock);
        switch (tmp) {
            case 0:
                ptr->result = thread_gestrec::FIST;
                break;
            case 1:
                ptr->result = thread_gestrec::ONE_FINGER;
                break;
            case 2:
                ptr->result = thread_gestrec::TWO_FINGER;
                break;
            case 3:
                ptr->result = thread_gestrec::THREE_FINGER;
                break;
            case 4:
                ptr->result = thread_gestrec::FOUR_FINGER;
                break;
            case 5:
                ptr->result = thread_gestrec::FIVE_FINGER;
                break;
            default:
                ptr->result = thread_gestrec::UNKNOWN;
        }
        pthread_rwlock_unlock(&ptr->rwlock);
    }
}

static void *gestrec_sub(void *obj) {
    auto ptr = (thread_mat *) obj;
    int result = 0;
    BackgroundSubtractorMOG2 g_BG_Model_2_Test(20, 16, true);
    GestureReconition_Cfg tCfg;
    GestureReconition_Data tData;
    cv::Mat tmp;
    pthread_rwlock_rdlock(&ptr->after_preproc.rwlock_preproc);
    ptr->after_preproc.mat_after_preproc.copyTo(tmp);
    pthread_rwlock_unlock(&ptr->after_preproc.rwlock_preproc);
    GR_LoadDefaultCfg(tCfg);
    GestureReconition(tCfg, tmp, tData, false, false, 0);
    pthread_exit(&tData.lFingerNum);
}